package com.colin.util;

import java.io.Serializable;
import java.security.SecureRandom;

public class TransIdGenerator implements Serializable {
	
	private static final long serialVersionUID = -4856846361193249489L;
	/**
	 * 此UUID的最大64位
	 */
	private final long mostSigBits;
	/**
	 * 此UUID的最低64位
	 */
	private final long leastSigBits;
	/**
	 * The random number generator used by this class to create random based
	 * UUIDs.
	 */
	private static volatile SecureRandom numberGenerator = null;
	/**
	 * Private constructor which uses a byte array to construct the new UUID.
	 */
	private TransIdGenerator(byte[] data) {
		long msb = 0;
		long lsb = 0;

		for (int i = 0; i < 8; i++)
			msb = (msb << 8) | (data[i] & 0xff);
		for (int i = 8; i < 16; i++)
			lsb = (lsb << 8) | (data[i] & 0xff);
		this.mostSigBits = msb;
		this.leastSigBits = lsb;
	}

	/**
	 * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
	 *
	 * The <code>UUID</code> is generated using a cryptographically strong
	 * pseudo random number generator.
	 *
	 * @return a randomly generated <tt>UUID</tt>.
	 */
	public static String randomUUID() {
		SecureRandom ng = numberGenerator;
		if (ng == null) {
			numberGenerator = ng = new SecureRandom();
		}

		byte[] randomBytes = new byte[16];
		ng.nextBytes(randomBytes);
		randomBytes[6] &= 0x0f; /* clear version */
		randomBytes[6] |= 0x40; /* set to version 4 */
		randomBytes[8] &= 0x3f; /* clear variant */
		randomBytes[8] |= 0x80; /* set to IETF variant */
		return new TransIdGenerator(randomBytes).toString();
	}

	/**
	 * Returns a <code>String</code> object representing this <code>UUID</code>.
	 * 
	 * <p>
	 * The UUID string representation is as described by this BNF : <blockquote>
	 * 
	 * <pre>
	 * {@code
	 * UUID                   = <time_low> "-" <time_mid> "-"
	 *                          <time_high_and_version> "-"
	 *                          <variant_and_sequence> "-"
	 *                          <node>
	 * time_low               = 4*<hexOctet>
	 * time_mid               = 2*<hexOctet>
	 * time_high_and_version  = 2*<hexOctet>
	 * variant_and_sequence   = 2*<hexOctet>
	 * node                   = 6*<hexOctet>
	 * hexOctet               = <hexDigit><hexDigit>
	 * hexDigit               =
	 *       "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
	 *       | "a" | "b" | "c" | "d" | "e" | "f"
	 *       | "A" | "B" | "C" | "D" | "E" | "F"
	 * }
	 * </pre>
	 * 
	 * </blockquote>
	 *
	 * @return a string representation of this <tt>UUID</tt>.
	 */
	public String toString() {

		return new StringBuilder(32).append(digits(mostSigBits >> 32, 8))
				.append(digits(mostSigBits >> 16, 4))
				.append(digits(mostSigBits, 4))
				.append(digits(leastSigBits >> 48, 4))
				.append(digits(leastSigBits, 12)).toString();

	}

	/** 
	 * Returns val represented by the specified number of hex digits. 
	 */
	private static String digits(long val, int digits) {
		long hi = 1L << (digits * 4);
		return Long.toHexString(hi | (val & (hi - 1))).substring(1);
	}

	public static void main(String[] args) {
		System.out.println(randomUUID());
	}

}
